#include <SPI.h>


#define VERSION         "1.0"
#define INFO            "EEPROM_CH552"
#define READY           "Ready"


#define LATCH 14
#define MOSI  15
#define MISO  16
#define SCK   17

#define CE    30
#define OE    31
#define V_11  32
#define V_OE  34

#define P165  33
#define OE595 11

// Buffers
#define BUFF_LEN 64
#define CMD_LEN  22

__xdata uint8_t pgBuffer[64];     // 写入芯片page缓存
__xdata unsigned char cmdBuffer[CMD_LEN];          // 串口命令缓存

void setAddress(uint32_t chipId,uint32_t addr) {

  if(chipId==2716){
    addr |= 0x800;
  }else{
    addr &= 0xfff;
  }
  
  uint8_t h = addr>>8 & 0xff;
  uint8_t l = addr & 0xff;

  SPI_transfer(h & 0xff);
  SPI_transfer(l & 0xff);

  digitalWrite(LATCH,HIGH);
  digitalWrite(LATCH,LOW);

}

void setup() {

  pinMode(P165,  OUTPUT);
  pinMode(LATCH, OUTPUT);
  pinMode(OE595, OUTPUT);
  pinMode(V_11,  OUTPUT);
  pinMode(V_OE,  OUTPUT);
  pinMode(OE,    OUTPUT);
  pinMode(CE,    OUTPUT);

  digitalWrite(P165, HIGH);//上升沿触发
  digitalWrite(LATCH,LOW);
  digitalWrite(OE595,HIGH);//1不输出
  digitalWrite(V_11, LOW);
  digitalWrite(V_OE, LOW);
  digitalWrite(OE,   HIGH);
  digitalWrite(CE,   HIGH);

  //配置SPI速率
  SPI_begin();
  //SPI_beginTransaction(8000000);
  // MSBFIRST 处理发送顺序
  SPI_beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));

//  setAddress(2732,0);

  while (!USBSerial()) {
    delay(50);
    //; // USB连接后才跳出循环
  }
}


// 读取串口发来的执行命令 如 x   2732  0000  0fff
void readCommand() {
  for(uint8_t i=0; i< CMD_LEN; i++) cmdBuffer[i] = 0;  // clear command buffer
  unsigned char c = 0xff; uint8_t idx = 0;                        // initialize variables
  do {
    if(USBSerial_available()) {
      c = USBSerial_read();
      cmdBuffer[idx++] = c;
    }
  } while (c != '\n' && idx < CMD_LEN);
  cmdBuffer[idx - 1] = 0;                     // change last newline to '\0' termination
}

// 返回字芯片字符串
uint16_t hexChip(char* dataa) {
  uint16_t re = 0;
//  if (dataa[0] >= 0x30 && dataa[0] <= 0x39)re += (dataa[0] - 0x30) * 100000;
//  if (dataa[1] >= 0x30 && dataa[1] <= 0x39)re += (dataa[1] - 0x30) * 10000;
  if (dataa[2] >= 0x30 && dataa[2] <= 0x39)re += (dataa[2] - 0x30) * 1000;
  if (dataa[3] >= 0x30 && dataa[3] <= 0x39)re += (dataa[3] - 0x30) * 100;
  if (dataa[4] >= 0x30 && dataa[4] <= 0x39)re += (dataa[4] - 0x30) * 10;
  if (dataa[5] >= 0x30 && dataa[5] <= 0x39)re += (dataa[5] - 0x30) * 1;
  return re;
}

uint8_t hexDigit(char c) {
  if      (c >= '0' && c <= '9') return c - '0';
  else if (c >= 'a' && c <= 'f') return c - 'a' + 10;
  else if (c >= 'A' && c <= 'F') return c - 'A' + 10;
  else return 0;
}


byte hexByte(char* a) {
  return ((hexDigit(a[0])*16) + hexDigit(a[1]));
}


uint16_t hexWord(char* dataa) {
  return ((hexDigit(dataa[0])*4096)+
    (hexDigit(dataa[1])*256)+
    (hexDigit(dataa[2])*16)+
    (hexDigit(dataa[3])));
}

uint8_t read165(){

  digitalWrite(CE,LOW);
  //读取延时
  delayMicroseconds(450);
  
  digitalWrite(P165,LOW);
  digitalWrite(P165,HIGH);
  uint8_t b = SPI_transfer(0xff);
  
  digitalWrite(CE,HIGH);
  return b;
}

void write595(uint16_t chipId,uint16_t addr,uint8_t bs){
  // 0xff 数据不写入
  if(bs==0xff)return;

  digitalWrite(OE595,LOW);//输出
  if(chipId==2732){
    addr &= 0xfff;
  }else{
    addr |= 0x800;
  }

  uint8_t h = addr>>8 & 0xff;
  uint8_t l = addr & 0xff;

  SPI_transfer(bs & 0xff);
  SPI_transfer(h & 0xff);
  SPI_transfer(l & 0xff);

  digitalWrite(LATCH,HIGH);
  digitalWrite(LATCH,LOW);

  delay(1);

  if(chipId==2732){
    //2732使用OE高压
    digitalWrite(V_OE, HIGH);
    digitalWrite(CE,LOW);
    delay(46);//45ms-55ms
    digitalWrite(CE,HIGH);
  }else{
    digitalWrite(CE,LOW);
    //2716使用V11
    digitalWrite(V_11, HIGH);
    digitalWrite(CE,HIGH);
    delay(46);//45ms-55ms
    digitalWrite(CE,LOW);
  }


  digitalWrite(V_11, LOW);
  digitalWrite(V_OE, LOW);
  digitalWrite(CE,HIGH);
  digitalWrite(OE595,HIGH);//停止
  
  delay(1);
}

void readChip(uint16_t chipId,uint16_t addr, uint16_t count) {
  digitalWrite(OE595,HIGH);//停用595输出
  
  digitalWrite(OE,LOW);

//  __xdata uint8_t tmp[16];
  while (count-- >0) {
    setAddress(chipId,addr);
    USBSerial_write(read165());
//    USBSerial_print(read165());
//    uint8_t a16 = addr & 0xf;
//    tmp[a16] = read165();
//    if (a16==0xf){
//      USBSerial_print_n(tmp,16); 
//    }
    addr++;
  }
  USBSerial_println("");
  USBSerial_flush();
  digitalWrite(OE,HIGH);
}

void writeChip(uint16_t chipId,uint16_t addr){
  for (uint8_t i=0; i<BUFF_LEN; i++) {
    while (!USBSerial_available());
    pgBuffer[i] = USBSerial_read();
  }
  uint16_t address = addr;

  digitalWrite(CE,HIGH);
  digitalWrite(OE,HIGH);
  for(uint8_t i=0; i<BUFF_LEN; i++){
    write595(chipId, address++, pgBuffer[i] & 0xff );
  }

  USBSerial_println("ok");
  USBSerial_flush();
}

void piptest(){
  for (uint8_t i=0; i<BUFF_LEN; i++) {
    while (!USBSerial_available());
    pgBuffer[i] = USBSerial_read();
  }
//  for(uint8_t i=0; i<BUFF_LEN; i++){
//    USBSerial_print(pgBuffer[i]);
//    USBSerial_flush();
//  }
  
  USBSerial_print_n(pgBuffer,BUFF_LEN);
  USBSerial_flush();
    
  USBSerial_println("ok");
  USBSerial_flush();
}

void t595(uint32_t chipId,uint16_t addr){
  digitalWrite(OE595,LOW);//输出
  if(chipId==2732){
    addr &= 0xfff;
  }else{
    addr |= 0x800;
  }

  uint8_t h = addr>>8 & 0xff;
  uint8_t l = addr & 0xff;

  SPI_transfer(l & 0xff);
  SPI_transfer(h & 0xff);
  SPI_transfer(l & 0xff);

  digitalWrite(LATCH,HIGH);
  digitalWrite(LATCH,LOW);
}


void checkChip(uint32_t chipId){
  if(chipId==2716 || chipId==2732){
    USBSerial_println("ok");
    USBSerial_flush();
  }else{
    USBSerial_println("Check chip unsupport");
    USBSerial_flush();
  }
}

// 循环
void loop() {
  readCommand();
  unsigned char cmd = cmdBuffer[0];                      //指令
  uint16_t chipId    = hexChip(cmdBuffer + 2);  //芯片
  uint16_t startAddr = hexWord(cmdBuffer + 10); //开始地址
  uint16_t endAddr   = hexWord(cmdBuffer + 16); //结束地址

  startAddr &= 0xffff;
  endAddr &= 0xffff;

  // 数据长度
  uint16_t dataLength = endAddr - startAddr + 1;

  // 初始化地址
//  setAddress(0);

  switch(cmd) {
    case 'i':   USBSerial_println(INFO);USBSerial_flush(); break;
    case 'v':   USBSerial_println(VERSION);USBSerial_flush(); break;
    case 't':   USBSerial_println(READY);USBSerial_flush(); break;
    //测试输入内容
    case 'r':   readChip(chipId, startAddr, dataLength); break;
    case 'w':   
                if (chipId==2716||chipId==2732) {
                  writeChip(chipId, startAddr);
                } else {
                  USBSerial_println("Write not support,chipId:");USBSerial_flush();
                  USBSerial_println(chipId);USBSerial_flush();
                }
                break;

    case 'p':   piptest(); break;
    case 'z':   t595(chipId,startAddr); break;

    case 'c':   checkChip(chipId); break;
    // a   2732  0000  0fff
    case 'a':   setAddress(chipId,startAddr); break;
    
    case 'x':   USBSerial_print(startAddr);USBSerial_println(" ");
                USBSerial_print(endAddr); USBSerial_println(" ");
                USBSerial_println(dataLength); 
                USBSerial_flush();
                break;
    default:    break;
  }    
}
